package com.spark.common.ext

import android.util.Log
import com.spark.common.Const
import okio.Buffer
import okio.BufferedSource
import okio.Okio
import org.json.JSONObject
import java.io.BufferedInputStream
import java.io.File
import java.io.FileOutputStream
import java.io.InputStream
import java.util.concurrent.Callable
import java.util.concurrent.Future
import java.util.concurrent.FutureTask

/**
 * 将任意代码块转为Future对象
 */
fun <T, R> T.toFuture(init: () -> R): Future<R> {
    return FutureTask<R>(Callable<R> { init() })
}

/**
 * 将 long 类型的时间格式化,
 * @ Long 的格式为毫秒
 * < 1 minute => 刚刚
 * > 1 minute => xxx 前
 */
fun Long.pretty(): String {
    val time = this / 1000
    return when (time) {
        in 0..1 -> {
            "刚刚"
        }
        in 1..60 -> {
            "$time 分钟前"
        }
        else -> {
            "$time 小时前"
        }
    }
}

/**
 * 将 map 参数转为 json 格式
 */
fun <T, U> MutableMap<T, U>.json(): String {
    val jo = JSONObject()
    forEach {
        jo.put(it.key.toString(), it.value.toString())
    }
    return jo.toString()
}


/**
 * 将 map 类型的参数生成json形式的 string
 * 最终提交的数据参数为 {"qr_jsonStr",{....}}
 */
fun <T> T.postParams(params: MutableMap<String, String>): MutableMap<String, String> {
    return mutableMapOf(Pair(Const.qr_jsonStr, params.json()))
}

/**
 * 判断是否为🈳️
 */
fun <T> T.isNull(): Boolean {
    return this == null
}

/**
 * 判断是否不为🈳️
 */
fun <T> T.isNotNull(): Boolean {
    return this != null
}

/**
 * 将 mutablelist<T> 展开，中间以 {@param id} 分隔开，最后一个没有
 */
fun <T> MutableList<T>.append(id: String): String {
    var result = ""
    forEachIndexed { i, t ->
        result += if (i < size - 1)
            "${t.toString()}$id"
        else
            t.toString()
    }
    return result
}

/**
 * 数字转为大写字母
 */
fun Int.toCN(): String {
    //数字对应的汉字
    val num = arrayOf("零", "一", "二", "三", "四", "五", "六", "七", "八", "九")
    //单位
    val unit = arrayOf("", "十", "百", "千", "万", "十", "百", "千", "亿", "十", "百", "千", "万亿")
    //将输入数字转换为字符串
    val result = this.toString()
    //将该字符串分割为数组存放
    val ch = result.toCharArray()
    //结果 字符串
    var str = ""
    val length = ch.size
    for (i in 0 until length) {
        val c = ch[i].toInt() - 48
        str += if (c != 0) {
            num[c] + unit[length - i - 1]
        } else {
            num[c]
        }
    }
    if (this % 10 == 0) {
        val indexOfLast = str.indexOfLast {
            it.toString() != "零"
        }
        str = str.substring(0, indexOfLast + 1)
    }
    return str
}

fun convert2CN(target: Int): String {
    return target.toCN()
}

fun InputStream.string(): String {
    val sb = StringBuffer()
    val buffer = ByteArray(4096)
    var len: Int = 0
    while (read(buffer).apply { len = this } > -1) {
        sb.append(String(buffer, 0, len))
    }
    close()
    return sb.toString()
}

fun InputStream.file(destFile: File, after: () -> Unit) {
    if (destFile.exists())
        destFile.delete()
    val fos = FileOutputStream(destFile)
    val bis = BufferedInputStream(this)
    val buffer = ByteArray(4096)
    var len: Int = 0
    while (bis.read(buffer).apply { len = this } > -1) {
        fos.write(buffer, 0, len)
        if (available() > 0)
            Log.d("【IO】", "【len】$len 【total】${available()} 【precent】${len / available()}")
    }
    after()
    fos.close()
    close()
}

fun BufferedSource.file(destFile: File, after: () -> Unit) {
    val bs = Okio.buffer(Okio.sink(destFile))
    val buffer = Buffer()
    var count: Long = 0
    while (read(buffer, 1024).apply { count = this } > -1) {
        bs.write(buffer, count)
    }
    after()
    close()
}